﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Text;
using System.Globalization;
using System.Collections;
using Carbon.Web.Forms.jQueryForms.Resx;
using System.Web.UI;

namespace Carbon.Web.Forms.jQueryForms
{
    public class jQueryFormsHandler : IHttpHandler
    {
        public bool IsReusable
        {
            get { return false; }
        }

        private static Dictionary<string, Action<HttpContext>> Mappings = new Dictionary<string, Action<HttpContext>>()
        {
            { ".jQueryFormsUi/upload.html", FileUpload },
            { ".jQueryFormsUi/resources.js", ResourcesHandler }
        };

        static jQueryFormsHandler()
        {
            foreach (String key in Mappings.Keys.ToArray())
            {
                Mappings[key.ToLowerInvariant()] = Mappings[key];
            }
        }

        private static void ResourcesHandler(HttpContext context)
        {
            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.Cache.SetMaxAge(new TimeSpan(1, 0, 0));
            context.Response.ContentType = "application/x-javascript";

            StringBuilder sb = new StringBuilder();

            sb.Append(
@"(function() {
    var Resources = { 
");
            bool first = true;

            foreach (DictionaryEntry entry in Carbon_Web_Forms_jQueryForms.ResourceManager.GetResourceSet(CultureInfo.InvariantCulture, true, false))
            {
                if (!first)
                    sb.AppendFormat(", ");

                String nValue = Resources.GetString((String)entry.Key);
                String value = null;

                if (nValue != null)
                    value = nValue;
                else
                    value = string.Empty;

                sb.AppendFormat("\"{0}\" : \"{1}\"", InternalUtility.EncodeJavascriptString((String)entry.Key), InternalUtility.EncodeJavascriptString(value));

                first = false;
            }

            sb.Append(
@" };

    Carbon_Web_Forms_jQueryForms_Resources_RegisterResources = function () {
        Type.registerNamespace('Carbon.Web.Forms.jQueryForms');
        
        Carbon.Web.Forms.jQueryForms.Resources = Resources;
    };

if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();
})();");

            context.Response.Write(sb.ToString());
        }

        private static void WriteFileUploadResponse(String id, Guid key, Exception ex, String command, HtmlTextWriter writer)
        {
            writer.Write(@"<html>
<body>
<form method=""POST"" action="""" enctype=""multipart/form-data"">
<input type=""file"" id=""upload"" name=""upload"" />");

            writer.Write(@"<input type=""text"" id=""id"" name=""id"" value=""{0}"" />", id);
            writer.Write(@"<input type=""text"" id=""key"" name=""key"" value=""{0}"" />", key);
            if (!string.IsNullOrEmpty(command))
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
                writer.AddAttribute(HtmlTextWriterAttribute.Id, "command");
                writer.AddAttribute(HtmlTextWriterAttribute.Name, "command");
                writer.AddAttribute(HtmlTextWriterAttribute.Value, command);
                writer.RenderBeginTag(HtmlTextWriterTag.Input);
                writer.RenderEndTag();
            }
            if (ex != null)
            {
                writer.AddAttribute(HtmlTextWriterAttribute.Type, "text");
                writer.AddAttribute(HtmlTextWriterAttribute.Id, "error");
                writer.AddAttribute(HtmlTextWriterAttribute.Name, "error");
                writer.AddAttribute(HtmlTextWriterAttribute.Value, ex.Message);
                writer.RenderBeginTag(HtmlTextWriterTag.Input);
                writer.RenderEndTag();
            }
            writer.Write(@"</form>
</body>
</html>
");


        }

        private static void FileUpload(HttpContext context)
        {
            HtmlTextWriter writer = new HtmlTextWriter(context.Response.Output);

            try
            {
                if (context.Request.HttpMethod == "GET")
                {
                    WriteFileUploadResponse("", Guid.Empty, null, null, writer);
                }
                else if (context.Request.HttpMethod == "POST")
                {
                    String command = context.Request["command"];

                    if (command == "Delete")
                    {
                        String id = ConvertInvariant.ToString(context.Request["id"]);
                        Guid key = new Guid(context.Request["key"]);

                        FormsContext.Current.PersistanceService.FreeFile(new FileReference(id, key, string.Empty));
                    }
                    else
                    {
                        HttpPostedFile file = context.Request.Files["upload"];
                        if (file == null) throw new NullReferenceException("file");

                        Guid reference = Guid.NewGuid();

                        String filename = file.FileName;

                        if (filename == null)
                            filename = string.Empty;

                        if (filename.Contains('\\'))
                            filename = filename.Substring(filename.LastIndexOf('\\') + 1);

                        if (filename.Contains('/'))
                            filename = filename.Substring(filename.LastIndexOf('/') + 1);

                        byte[] content = new byte[file.InputStream.Length];
                        int result = file.InputStream.Read(content, 0, content.Length);

                        if ((result == content.Length) == false) throw new InvalidOperationException("(result == content.Length) == false");
                        FileReference fileReference = FormsContext.Current.PersistanceService.StoreFile(reference, filename, content);

                        String serializedId = InternalUtility.CompactSerialize(fileReference.Id);
                        WriteFileUploadResponse(serializedId, fileReference.Key, null, "Delete", writer);
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                WriteFileUploadResponse("", Guid.Empty, ex, null, writer);
            }
        }

        public void ProcessRequest(HttpContext context)
        {
            String mapping = context.Request.Url.GetComponents(UriComponents.Path, UriFormat.Unescaped).ToLowerInvariant();

            if (!Mappings.ContainsKey(mapping))
                throw new InvalidOperationException("Unknown path");

            Mappings[mapping](context);
        }
    }
}